<?xml version="1.0" encoding="utf-8" ?>
<!-- 

  NxBRE - Native syntax rendering of xBusinessRules

  Author: David Dossot

-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="rulesDir"/>

<!-- id generator -->
<xsl:template name="id-gen">
	<xsl:param name="id" select="@id"/>
	<xsl:choose>
		<xsl:when test="$id!=''">
			<xsl:attribute name="id"><xsl:value-of select="$id"/></xsl:attribute>
		</xsl:when>
		<xsl:otherwise>
			<xsl:attribute name="id">#dummy<xsl:value-of select="generate-id(.)"/><xsl:value-of select="position()"/>#</xsl:attribute>
		</xsl:otherwise>
	</xsl:choose>
</xsl:template>

<!-- identity transform -->
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

<!-- transform extended rules in NxBRE rules -->
<xsl:template match="xBusinessRules">
	<BusinessRules	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
									xsi:noNamespaceSchemaLocation="http://nxbre.org/businessRules.xsd">
		<xsl:comment> BusinessRules generated by transformXRules.xsl </xsl:comment>
		<Rule id="#true#" factory="NxBRE.FlowEngine.Rules.True"/>
		<Rule id="#false#" factory="NxBRE.FlowEngine.Rules.False"/>
		<xsl:apply-templates/>
	</BusinessRules>
</xsl:template>

<!-- logical types to .NET types -->
<xsl:template name="type-conv">
	<xsl:param name="type" select="@type"/>
	<xsl:choose>
		<xsl:when test="$type='Exception'">System.Exception</xsl:when>
		<xsl:when test="$type='Boolean'">System.Boolean</xsl:when>
		<xsl:when test="$type='Byte'">System.SByte</xsl:when>
		<xsl:when test="$type='Short'">System.Int16</xsl:when>
		<xsl:when test="$type='Integer'">System.Int32</xsl:when>
		<xsl:when test="$type='Long'">System.Int64</xsl:when>
		<xsl:when test="$type='Single'">System.Single</xsl:when>
		<xsl:when test="$type='Double'">System.Double</xsl:when>
		<xsl:when test="$type='Decimal'">System.Decimal</xsl:when>
		<xsl:when test="$type='Date'">System.DateTime</xsl:when>
		<xsl:when test="$type='DateTime'">System.DateTime</xsl:when>
		<xsl:when test="$type='Time'">System.DateTime</xsl:when>
		<xsl:when test="$type='String'">System.String</xsl:when>
		<xsl:otherwise><xsl:value-of select="$type"/></xsl:otherwise>
	</xsl:choose>
</xsl:template>
<xsl:template match="Exception | Boolean | Byte | Short | Integer | Long | Single | Double | Decimal | Date | DateTime | Time | String">
	<Rule id="{@id}" factory="NxBRE.FlowEngine.Rules.Value">
		<Parameter name="Value" value="{@value}"/>
		<Parameter name="Type">
			<xsl:attribute name="value">
				<xsl:call-template name="type-conv">
					<xsl:with-param name="type" select="name()"/>
				</xsl:call-template>
			</xsl:attribute>
		</Parameter>
	</Rule>
</xsl:template>
<xsl:template match="Parameter[@name='Type']">
	<Parameter name="Type">
		<xsl:attribute name="value">
			<xsl:call-template name="type-conv">
				<xsl:with-param name="type" select="@value"/>
			</xsl:call-template>
		</xsl:attribute>
	</Parameter>
</xsl:template>
<xsl:template match="Parameter[@name!='Type' and @valueId!='']">
	<Parameter name="{@name}" ruleValue="{@valueId}"/>
</xsl:template>
<xsl:template match="Argument">
	<Parameter name="Argument{position()-1}">
		<xsl:if test="@type != ''">
			<xsl:attribute name="type">
				<xsl:call-template name="type-conv">
					<xsl:with-param name="type" select="@type"/>
				</xsl:call-template>
			</xsl:attribute>
		</xsl:if>
		<xsl:if test="@valueId != ''">
			<xsl:attribute name="ruleValue">
				<xsl:value-of select="@valueId"/>
			</xsl:attribute>
		</xsl:if>
		<xsl:copy-of select="@value"/>
	</Parameter>
</xsl:template>

<!-- conditions -->
<xsl:template match="And">
	<Condition type="AND">
		<xsl:apply-templates/>
	</Condition>
</xsl:template>
<xsl:template match="Or">
	<Condition type="OR">
		<xsl:apply-templates/>
	</Condition>
</xsl:template>
<xsl:template match="Not">
	<Condition type="NOT">
		<xsl:apply-templates/>
	</Condition>
</xsl:template>

<!-- operators -->
<xsl:template match="Equals | GreaterThan | GreaterThanEqualTo | InstanceOf | LessThan | LessThanEqualTo | NotEquals">
	<Compare leftId="{@leftId}" operator="NxBRE.FlowEngine.Rules.{name()}" rightId="{@rightId}">
		<xsl:apply-templates/>
	</Compare>
</xsl:template>
<xsl:template match="Matches">
	<Compare leftId="{@valueId}" operator="NxBRE.FlowEngine.Rules.{name()}" rightId="{@patternId}">
		<xsl:apply-templates/>
	</Compare>
</xsl:template>
<xsl:template name="in-values">
	<xsl:param name="idList" select="@idList"/>
	<xsl:choose>
		<xsl:when test="contains($idList, ',')">
			<Compare leftId="{@valueId}" operator="NxBRE.FlowEngine.Rules.Equals" rightId="{substring-before($idList,',')}">
				<xsl:apply-templates/>
			</Compare>
			<xsl:call-template name="in-values">
				<xsl:with-param name="idList" select="substring-after($idList,',')"/>
			</xsl:call-template>
		</xsl:when>
		<xsl:otherwise>
			<Compare leftId="{@valueId}" operator="NxBRE.FlowEngine.Rules.Equals" rightId="{$idList}">
				<xsl:apply-templates/>
			</Compare>
		</xsl:otherwise>
	</xsl:choose>
</xsl:template>
<xsl:template match="In">
	<Condition type="OR">
		<xsl:call-template name="in-values"/>
	</Condition>
</xsl:template>
<xsl:template match="IsAsserted">
	<Compare leftId="{@valueId}" operator="NxBRE.FlowEngine.Rules.InstanceOf" rightId="{@valueId}"/>
</xsl:template>
<xsl:template match="IsTrue">
	<Compare leftId="{@valueId}" operator="NxBRE.FlowEngine.Rules.Equals" rightId="#true#">
		<xsl:apply-templates/>
	</Compare>
</xsl:template>
<xsl:template match="IsFalse">
	<Compare leftId="{@valueId}" operator="NxBRE.FlowEngine.Rules.Equals" rightId="#false#">
		<xsl:apply-templates/>
	</Compare>
</xsl:template>
<xsl:template match="Between">
	<Condition type="AND">
		<Compare leftId="{@leftId}" rightId="{@valueId}">
			<xsl:attribute name="operator">
				<xsl:choose>
					<xsl:when test="@excludeLeft='true'">NxBRE.FlowEngine.Rules.LessThan</xsl:when>
					<xsl:otherwise>NxBRE.FlowEngine.Rules.LessThanEqualTo</xsl:otherwise>
				</xsl:choose>
			</xsl:attribute>
			<xsl:apply-templates/>
		</Compare>
		<Compare leftId="{@valueId}" rightId="{@rightId}">
			<xsl:attribute name="operator">
				<xsl:choose>
					<xsl:when test="@excludeRight='true'">NxBRE.FlowEngine.Rules.LessThan</xsl:when>
					<xsl:otherwise>NxBRE.FlowEngine.Rules.LessThanEqualTo</xsl:otherwise>
				</xsl:choose>
			</xsl:attribute>
			<xsl:apply-templates/>
		</Compare>
	</Condition>
</xsl:template>
<xsl:template match="ForEach">
	<ForEach id="{@id}" ruleValue="{@valueId}">
		<xsl:apply-templates/>
	</ForEach>
</xsl:template>

<!-- object related rules -->
<xsl:template match="Assert | Evaluate | Modify">
	<Rule id="{@id}">
		<xsl:if test="name()='Assert'">
			<xsl:attribute name="factory">NxBRE.FlowEngine.Rules.Value</xsl:attribute>
		</xsl:if>
		<Parameter name="Type">
			<xsl:attribute name="value">
				<xsl:call-template name="type-conv"/>
			</xsl:attribute>
		</Parameter>
		<xsl:choose>
			<xsl:when test="@valueId!=''">
				<Parameter name="Value" ruleValue="{@valueId}"/>
			</xsl:when>
			<xsl:when test="@value!=''">
				<Parameter name="Value" value="{@value}"/>
			</xsl:when>
		</xsl:choose>
		<xsl:apply-templates/>
	</Rule>
</xsl:template>
<xsl:template match="ObjectLookup">
	<Rule factory="NxBRE.FlowEngine.Rules.ObjectLookup">
		<xsl:call-template name="id-gen"/>
		<xsl:if test="@objectId != ''">
			<Parameter name="ObjectId" value="{@objectId}"/>
		</xsl:if>
		<xsl:if test="@member != ''">
			<Parameter name="Member" value="{@member}"/>
		</xsl:if>
		<xsl:if test="@type != ''">
			<Parameter name="Type" value="{@type}"/>
		</xsl:if>
		<xsl:apply-templates/>
	</Rule>
</xsl:template>

<!-- set related rules -->
<xsl:template match="InvokeSet">
	<InvokeSet>
		<xsl:if test="@id != ''">
			<xsl:attribute name="id">
				<xsl:value-of select="@id"/>
			</xsl:attribute>
		</xsl:if>
		<xsl:if test="@valueId != ''">
			<xsl:attribute name="ruleValue">
				<xsl:value-of select="@valueId"/>
			</xsl:attribute>
		</xsl:if>
	</InvokeSet>
</xsl:template>

<!-- Increment -->
<xsl:template match="Increment[@step]">
	<Rule id="{@id}" factory="NxBRE.FlowEngine.Rules.Increment">
		<Parameter name="Increment" value="{@step}"/>
	</Rule>
</xsl:template>
<xsl:template match="Increment[count(@step)=0]">
	<Rule factory="NxBRE.FlowEngine.Rules.IncrementInit">
		<xsl:call-template name="id-gen">
			<xsl:with-param name="id"/>
		</xsl:call-template>
		<Parameter name="Id" value="{@id}"/>
		<xsl:if test="@valueId!=''">
			<Parameter name="Init" ruleValue="{@valueId}"/>
		</xsl:if>
		<xsl:if test="@value!=''">
			<Parameter name="Init" value="{@value}"/>
		</xsl:if>
	</Rule>
</xsl:template>

<!-- other rules -->
<xsl:template match="True">
	<Rule id="{@id}" factory="NxBRE.FlowEngine.Rules.True"/>
</xsl:template>
<xsl:template match="False">
	<Rule id="{@id}" factory="NxBRE.FlowEngine.Rules.False"/>
</xsl:template>
<xsl:template match="ThrowException | ThrowFatalException">
	<Rule factory="NxBRE.FlowEngine.Rules.{substring-after(name(),'Throw')}">
		<xsl:call-template name="id-gen"/>
		<xsl:if test="@value!=''">
			<Parameter name="Message" value="{@value}"/>
		</xsl:if>
		<xsl:if test="@valueId!=''">
			<Parameter name="Message" ruleValue="{@valueId}"/>
		</xsl:if>
	</Rule>
</xsl:template>
</xsl:stylesheet>

